import base64
import json
import random
import time
import warnings
from base64 import b64encode
from pathlib import Path

import ddddocr
import execjs
import requests
import rsa
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from loguru import logger
from retrying import retry

from utils.proxies_tools import get_company_ip_crawler_by_api
from utils.rs_utils.rs6 import Rs6Session

warnings.filterwarnings("ignore")


def get_random_num(t=16):
    e = [
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "A",
        "B",
        "C",
        "D",
        "E",
        "F",
        "G",
        "H",
        "I",
        "J",
        "K",
        "L",
        "M",
        "N",
        "O",
        "P",
        "Q",
        "R",
        "S",
        "T",
        "U",
        "V",
        "W",
        "X",
        "Y",
        "Z",
        ".",
        "?",
        "~",
        "!",
        "@",
        "#",
        "$",
        "%",
        "^",
        "&",
        "*",
    ]
    return "".join([e[random.randint(0, 45)] for _ in range(t)])


def aes_encrypt(text, key):
    encryptor = AES.new(key.encode("utf-8"), AES.MODE_ECB)
    pad_pkcs7 = pad(text.encode("utf-8"), AES.block_size, style="pkcs7")
    ciphertext = base64.b64encode(encryptor.encrypt(pad_pkcs7)).decode()
    return ciphertext


def encrypt_aes_key(text: str):
    pem = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJyQCGUo+5Hg1dtOjzXC5GTUlWgiVg2U\nggYlPSgM4fE39wfJ3qJWOLYKSzGxpLhZtBSbMBJfJja60nSLdBJpAKcCAwEAAQ==\n-----END PUBLIC KEY-----"
    rsa_pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(pem.encode())
    ciphertext = rsa.encrypt(text.encode(), rsa_pubkey)
    ciphertext_b64 = b64encode(ciphertext).decode("utf-8")
    return ciphertext_b64


class CpOnlineLogin(Rs6Session):
    def __init__(self, cookies=None, proxies=None):
        if proxies is None:
            proxies = get_company_ip_crawler_by_api(static=True)
        super().__init__(proxies=proxies, cookies=None, debug=False)
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
            "Accept-Encoding": "gzip, deflate, br, zstd",
            "sec-ch-ua-platform": '"Windows"',
            "sec-ch-ua": '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
            "Content-Type": "application/json;charset=UTF-8",
            "sec-ch-ua-mobile": "?0",
            "Origin": "https://tysf.cponline.cnipa.gov.cn",
            "Sec-Fetch-Site": "same-origin",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Dest": "empty",
            "Referer": "https://tysf.cponline.cnipa.gov.cn/am/",
            "Accept-Language": "zh-CN,zh;q=0.9,zu;q=0.8,be;q=0.7,en;q=0.6",
        }
        self.session = requests.Session()
        self.session.verify = False
        self.session.proxies = self.proxies
        logger.info(f"正在初始化 CPOnlineLogin proxies {self.session.proxies}")
        self.session.headers = self.headers
        if cookies:
            self.session.cookies.update(cookies)
        js_code = (Path(__file__).parent / "des.js").read_text()
        self.ctx = execjs.compile(js_code)

    def check_is_auth(self):
        url = f"https://tysf.cponline.cnipa.gov.cn/am/auth/isAuth?sendleTime={int(time.time()*1000)}"
        res = self.session.get(url)
        logger.info(f"账号是否已经登录：{res.text}")
        if res.text == "true":
            return True
        return False

    def get_random_code(self):
        url = "https://tysf.cponline.cnipa.gov.cn/am/auth/getRandomCode"
        res = self.session.post(url).json()
        return res["data"]

    def _get_captcha_uuid(self):
        """生成符合UUIDv4格式的字符串（简化版）"""
        e = []
        for i in range(36):
            e.append(random.choice("0123456789abcdef"))

        # 根据UUIDv4规范设置特定位置的字符
        e[14] = "4"  # 版本标识位
        e[19] = format((int(e[19], 16) & 0x3) | 0x8, "x")  # 变体标识位
        # 设置分隔符
        e[8] = e[13] = e[18] = e[23] = "-"

        return "".join(e)

    def get_and_verify_captcha(self):
        url = "https://tysf.cponline.cnipa.gov.cn/am/captcha/get"
        data = {
            "captchaType": "blockPuzzle",
            "clientUid": f"slider-{self._get_captcha_uuid()}",
            "ts": int(time.time() * 1000),
        }
        res = self.session.post(url, json=data)
        resp = res.json()
        jigsaw_image_base64 = resp["repData"]["jigsawImageBase64"]
        original_image_base64 = resp["repData"]["originalImageBase64"]
        token = resp["repData"]["token"]
        logger.debug(f"正在验证图片 {token}")
        ocr = ddddocr.DdddOcr(det=True, show_ad=False)
        jigsaw_image_base64 = base64.b64decode(jigsaw_image_base64)
        original_image_base64 = base64.b64decode(original_image_base64)
        result = ocr.slide_match(target_bytes=jigsaw_image_base64, background_bytes=original_image_base64)
        point = {"x": result.get("target")[0], "y": 5}
        captcha_data = {
            "captchaType": "blockPuzzle",
            "pointJson": json.dumps(point, separators=(",", ":")),
            "token": token,
        }
        url = "https://tysf.cponline.cnipa.gov.cn/am/captcha/check"
        result_res = self.session.post(url, json=captcha_data).json()
        logger.debug(f"图片验证结果 {result_res}")
        if result_res["repData"]["result"] is True:
            return True
        return False

    @retry(stop_max_attempt_number=3, wait_fixed=1000)
    def verify_captcha(self, username, password):
        random_code = self.get_random_code()
        self.get_and_verify_captcha()
        url = "https://tysf.cponline.cnipa.gov.cn/am/login"
        login_password = self.ctx.call("strEnc", password, random_code, "", "")
        data = {
            "callbackVOList": [
                {
                    "callback": {
                        "loginName": username,
                        "moduleName": "PasswordModule",
                        "prompt": "用户名",
                        "step": 1,
                        "subjectNeedFill": True,
                    },
                    "callbackType": "cn.org.bjca.am.authframework.callback.LoginNameCallback",
                    "order": 0,
                },
                {
                    "callback": {
                        "encoding": False,
                        "moduleName": "PasswordModule",
                        "password": login_password,
                        "prompt": "密码",
                        "step": 1,
                        "subjectNeedFill": True,
                    },
                    "callbackType": "cn.org.bjca.am.authframework.callback.PasswordCallback",
                    "order": 1,
                },
                {
                    "callback": {
                        "choices": {"1": "个人用户", "2": "单位用户", "3": "代办人"},
                        "defaultChoice": "",
                        "moduleName": "PasswordModule",
                        "multipleSelectionsAllowed": False,
                        "prompt": "111",
                        "selectedKey": "1",
                        "step": 1,
                        "subjectNeedFill": True,
                    },
                    "callbackType": "cn.org.bjca.am.authframework.callback.ChoiceCallback",
                    "order": 2,
                },
                {
                    "callback": {
                        "moduleName": "PasswordModule",
                        "prompt": "验证码",
                        "step": 1,
                        "subjectNeedFill": True,
                        "validateCode": "",
                    },
                    "callbackType": "cn.org.bjca.am.authframework.callback.ValidateCodeCallback",
                    "order": 3,
                },
                {
                    "callback": {"moduleName": "PasswordModule", "step": 1, "subjectNeedFill": True, "type": ""},
                    "callbackType": "cn.org.bjca.am.authframework.callback.AppTypeCallback",
                    "order": 4,
                },
            ],
            "indexName": "initService",
            "indexType": "service",
            "moduleName": "PasswordModule",
            "step": 1,
        }
        res = self.session.post(url, json=data).json()
        logger.debug(f"登录跳转结果 {res} {self.session.cookies.get_dict()}")
        if res["message"] == "成功":
            return res
        else:
            raise Exception(res)

    def _init_(self):
        oauth_login_url = self.request_core(
            "https://pss-system.cponline.cnipa.gov.cn/api/userCenter/oauthLogin", verify=False
        ).json()["t"]["url"]
        self.session.get(oauth_login_url)

    def login(self, username="15869175424", password="fuppyfSupfuk!1"):
        self._init_()
        if self.check_is_auth() is False:
            res = self.verify_captcha(username, password)
            if res["message"] == "成功":
                redirect_url = "https:" + res["data"]["callback"]["redirectURL"]
                res = self.session.get(redirect_url, verify=False)
                code = res.history[-1].headers.get("Location").split("code=")[-1]
                if code:
                    url = "https://pss-system.cponline.cnipa.gov.cn/api/userCenter/ess"
                    data = {"code": code}
                    auth_response = self.request_core(
                        url,
                        json=data,
                        method="POST",
                        verify=False,
                        headers={
                            **self.headers,
                            "language": "zh",
                            "Authorization": "*",
                            "EncryptAesKey": "null",
                            "Content-Type": "application/json;charset=UTF-8",
                            "Origin": "https://pss-system.cponline.cnipa.gov.cn",
                            "Referer": f"https://pss-system.cponline.cnipa.gov.cn/Initpage?code={code}",
                        },
                    )
                    logger.debug(f"登录结果 {auth_response.text}")
                    if auth_response.status_code == 200:
                        auth_code = auth_response.json().get("t")
                        logger.info(f"登录token {auth_code}")
                        return auth_code
        else:
            raise Exception("已经登录")

    def load_user(self):
        url = "https://tysfjk.cponline.cnipa.gov.cn/portal/user/loadUser"
        res = self.session.post(url).text
        logger.debug(f"用户信息 {res}")


if __name__ == "__main__":
    cp = CpOnlineLogin(proxies={})
    cp.login()
